package com.sky.aspect;

import com.sky.anno.AutoClearCache;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

import java.lang.reflect.Method;

//@Aspect
//@Component
@Slf4j
public class CacheClearAspect {

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 切入点：所有被@AutoClearCache注解的方法
     */
    @Pointcut("@annotation(com.sky.anno.AutoClearCache) && execution(* com.sky.service.*.*(..))")
    public void cacheClearPointcut() {
    }

    /**
     * 后置通知：方法执行成功后清理缓存
     */
    @AfterReturning("cacheClearPointcut()")
    public void autoClearCache(JoinPoint joinPoint) {
        log.info("开始执行缓存清理...");

        try {
            // 获取方法签名和注解
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            Method method = signature.getMethod();
            AutoClearCache autoClearCache = method.getAnnotation(AutoClearCache.class);

            // 获取注解属性
            String cachePrefix = autoClearCache.value();
            String keyExpression = autoClearCache.key();
            boolean isPattern = autoClearCache.pattern();

            // 构建完整的缓存键
            String cacheKey = buildCacheKey(cachePrefix, keyExpression, joinPoint);

            // 执行缓存清理
            if (isPattern) {
                clearPatternKeys(cacheKey);
            } else {
                clearSingleKey(cacheKey);
            }

            log.info("缓存清理完成: {}", cacheKey);
        } catch (Exception e) {
            log.error("清理缓存失败", e);
        }
    }

    /**
     * 构建缓存键
     */
    private String buildCacheKey(String prefix, String keyExpression, JoinPoint joinPoint) {
        if (keyExpression.isEmpty()) {
            return prefix;
        }

        try {
            // 使用SpEL表达式解析键值
            ExpressionParser parser = new SpelExpressionParser();
            StandardEvaluationContext context = new StandardEvaluationContext();

            // 设置参数上下文
            Object[] args = joinPoint.getArgs();
            String[] parameterNames = ((MethodSignature) joinPoint.getSignature()).getParameterNames();

            for (int i = 0; i < parameterNames.length; i++) {
                context.setVariable(parameterNames[i], args[i]);
            }

            // 解析表达式
            Expression expression = parser.parseExpression(keyExpression);
            Object keyValue = expression.getValue(context);

            return prefix + keyValue;
        } catch (Exception e) {
            log.warn("解析SpEL表达式失败，使用默认键: {}", keyExpression);
            return prefix;
        }
    }

    /**
     * 清理单个缓存键
     */
    private void clearSingleKey(String key) {
        Boolean result = redisTemplate.delete(key);
        log.info("清理缓存键: {}{}", key, result ? "成功" : "键不存在");
    }

    /**
     * 清理模式匹配的缓存键
     */
    private void clearPatternKeys(String pattern) {
        try {
            redisTemplate.delete(redisTemplate.keys(pattern));
            log.info("清理模式匹配缓存: {}", pattern);
        } catch (Exception e) {
            log.error("清理模式匹配缓存失败: {}", pattern, e);
        }
    }
}